home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-05 / drivers1.zip / EN301.ASM < prev    next >
Assembly Source File  |  1992-01-23  |  26KB  |  866 lines

  1. version        equ     1
  2. ;******************************************************************************;
  3. ;*    File:    EN301.ASM
  4. ;*        Packet Driver for Multi-Tech Systems EN301xx series
  5. ;*        ETHERNET adapters.
  6. ;*      Auth:    Chris Elmquist    N0JCF
  7. ;*    Date:    April 1, 1991
  8. ;*        Removed Microchannel support and added code to
  9. ;*        support serial EEPROM on Multi-Tech card.
  10. ;*
  11. ;*   Copyright (C) 1991  Chris Elmquist
  12. ;*
  13. ;*   This program is free software; you can redistribute it and/or modify
  14. ;*   it under the terms of the GNU General Public License as published by
  15. ;*   the Free Software Foundation; either version 1, or (at your option)
  16. ;*   any later version.
  17. ;*
  18. ;*   This program is distributed in the hope that it will be useful,
  19. ;*   but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. ;*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21. ;*   GNU General Public License for more details.
  22. ;*
  23. ;*   You should have received a copy of the GNU General Public License
  24. ;*   along with this program; if not, write to the Free Software
  25. ;*   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  26. ;*
  27. ;******************************************************************************;
  28. ;*        Original work from:                          *;
  29. ;*                        File: TiaraFTP.ASM                          *;
  30. ;*                 Auth: Brian Fisher                          *;
  31. ;*                       Queens University                             *;
  32. ;*                       Computing and Communications Services         *;
  33. ;*                       Rm 2-50 Dupuis Hall                           *;
  34. ;*                       Kingston Ontario                              *;
  35. ;*                Date: January 24 1990                         *;
  36. ;*============================================================================*;
  37. ;*     Revs: January 25 1990   V 1.6.0 Clean up code and document.            *;
  38. ;*           Feb     24 1991   V 1.8.2 Gets IRQ and I/O info from MCH POS regs*;
  39. ;*                                                                            *;
  40. ;*============================================================================*;
  41. ;*                                                                            *;
  42. ;*     Thanks, Mehdi Safipour, of Tiara Computer Systems, who supplied the    *;
  43. ;*     programming manual and examples.                                       *;
  44. ;*                                                                            *;
  45. ;*============================================================================*;
  46. ;*                                                                            *;
  47. ;*     Logic -                                                                *;
  48. ;*                                                                            *;
  49. ;*     Initialization - classic, by-the-book initialization, with one         *;
  50. ;*     exception:  The manual didn't mention the fact that receive            *;
  51. ;*     interrupts will not always work unless the receive buffer is           *;
  52. ;*     vacuumed.                                                              *;
  53. ;*                                                                            *;
  54. ;*     Byte/Word I/O mode was determined by code ruthlessly copied from       *;
  55. ;*     NI5010.ASM, auth: Russ Nelson.                                         *;
  56. ;*                                                                            *;
  57. ;*     Transmit-no surprises, data goes whoosh!                               *;
  58. ;*                                                                            *;
  59. ;*     Receive-interrupt driven receive makes upcalls to inform the ULP of    *;
  60. ;*     its status.  The 14 byte ethernet header is copied from the card to    *;
  61. ;*     a temporary buffer, to determine the ether-type.  Recv_find is called  *;
  62. ;*     to acquire a buffer from the ULP.  If no buffer, the packet is dropped.*;
  63. ;*     If a buffer is acquired, the packet is copied into it, and recv_copy   *;
  64. ;*     informs the ULP that the data is there.                                *;
  65. ;*                                                                            *;
  66. ;******************************************************************************;
  67. ;
  68.  
  69. DLCR_XMIT_STAT EQU     0               ; EtherStar I/O Register offsets
  70. DLCR_XMIT_MASK EQU     1
  71. DLCR_RECV_STAT EQU     2
  72. DLCR_RECV_MASK EQU     3
  73. DLCR_XMIT_MODE EQU     4
  74. DLCR_RECV_MODE EQU     5
  75. DLCR_ENABLE    EQU     6
  76. DLCR_TDR_LOW   EQU     7
  77. DLCR_NODE_ID   EQU     8
  78. DLCR_TDR_HIGH  EQU     0FH
  79. BMPR_MEM_PORT  EQU     10H
  80. BMPR_PKT_LEN   EQU     12H
  81. BMPR_DMA_ENABLE EQU    14H
  82. EECS_PORT    EQU    18H
  83. EECLK_PORT    EQU    19H
  84. EEDI_PORT    EQU    1AH
  85. EEDO_PORT    EQU    1AH
  86. TMST           EQU     80h
  87. TMT_OK         EQU     80h
  88. BUF_EMPTY      EQU     40h
  89. card_disable   equ     80h             ; written to DLCR_ENABLE to disable card
  90. card_enable    equ     0h              ; written to DLCR_ENABLE to enable card
  91. clear_status   equ     00001111B       ; used to clear status info
  92. ;
  93. ;                      !!!!!!!!--------
  94. ;                      !!!!!!!+--------CLEAR BUS WRITE ERROR
  95. ;                      !!!!!!+---------CLEAR 16 COLLISION
  96. ;                      !!!!!+----------CLEAR COLLISION
  97. ;                      !!!!+-----------CLEAR UNDERFLOW
  98. ;                      !!!+------------NC
  99. ;                      !!+-------------NC
  100. ;                      !+--------------NC
  101. ;                      +---------------NC
  102. ;
  103. no_tx_irqs      equ     0              ; written to clear transmit IRQs
  104. clr_rcv_status  equ     0CFh           ; clears receive status
  105. en_rcv_irqs     equ     10000000B      ; enable receive interrupts
  106. ;
  107. ;                      !!!!!!!!--------
  108. ;                      !!!!!!!+--------ENABLE OVERFLOW
  109. ;                      !!!!!!+---------ENABLE CRC
  110. ;                      !!!!!+----------ENABLE ALIGN
  111. ;                      !!!!+-----------ENABLE SHORT PKT
  112. ;                      !!!+------------DISABLE REMOTE RESET
  113. ;                      !!+-------------RESERVED
  114. ;                      !+--------------RESERVED
  115. ;                      +---------------ENABLE PKT READY
  116. ;
  117. xmit_mode       equ     00000010B
  118. ;
  119. ;ENABLE CARRIER DETECT
  120. ;
  121. ;DISABLE LOOPBACK
  122. ;
  123. recv_mode       equ     00000010B                 ; set receive mode
  124. ;
  125. ;                       !!!!!!!!---------ACCEPT ALL PACKETS
  126. ;                       !!!!!!!+---------ACCEPT PHYSICAL, MULTICAST, AND
  127. ;                       !!!!!!+----------BROADCAST PACKETS
  128. ;                       !!!!!+-----------DISABLE REMOTE RESET
  129. ;                       !!!!+------------DISABLE SHORT PACKETS
  130. ;                       !!!+-------------USE 6 BYTE ADDRESS
  131. ;                       !!+--------------NC
  132. ;                       !+---------------NC
  133. ;                       +----------------DISABLE CRC TEST MODE
  134.  
  135. debug    = 0
  136.  
  137.     include defs.asm
  138.  
  139. code segment word public
  140.     assume  cs:code, ds:code
  141.  
  142.     public  int_no, eeaddr
  143. int_no    db      3,0,0,0            ;must be four bytes long for get_number
  144. io_adr    dw    300h,0            ; default I/O address
  145. is_186    db      0            ; set to 1 if 186, 286, 386 word mode
  146. eeaddr    db    0,0,0,0,0,0        ; store a copy of EEPROM Ethernet addr
  147.  
  148.     public    driver_class, driver_type, driver_name, driver_function, parameter_list
  149. driver_class    db      BLUEBOOK,IEEE8023,0    ;from the packet spec
  150. driver_type    db      1        ;from the packet spec
  151. driver_name    db      'EN301FTP',0    ;name of the driver.
  152. driver_function    db    2
  153. parameter_list    label    byte
  154.     db    1    ;major rev of packet driver
  155.     db    0    ;minor rev of packet driver
  156.     db    14    ;length of parameter list
  157.     db    EADDR_LEN    ;length of MAC-layer address
  158.     dw    GIANT    ;MTU, including MAC headers
  159.     dw    MAX_MULTICAST * EADDR_LEN    ;buffer size of multicast addrs
  160.     dw    0    ;(# of back-to-back MTU rcvs) - 1
  161.     dw    0    ;(# of successive xmits) - 1
  162. int_num    dw    0    ;Interrupt # to hook for post-EOI
  163.             ;processing, 0 == none,
  164.  
  165.     public  rcv_modes
  166. rcv_modes    dw    7        ;number of receive modes in our table.
  167.         dw    0               ;There is no mode zero
  168.         dw    rcv_mode_1
  169.         dw    0
  170.         dw    rcv_mode_3
  171.         dw    0        ;haven't set up perfect filtering yet.
  172.         dw    0
  173.         dw    rcv_mode_6
  174.  
  175.  
  176. ;
  177. ;      Receive Packet Header Buffer: Required because addresses and e-type
  178. ;      must be read from Tiara card before upcall to find a buffer can be
  179. ;      made.  Need the number of bytes, and the e-type for the call...
  180. ;
  181. ether_buff    db    EADDR_LEN  dup(?)
  182.         db    EADDR_LEN  dup(?)
  183. ether_type    db    4 dup(?)
  184. usr_ptr        dd    ?                 ; temp storage or recv_buff ptr
  185.  
  186. writebport  macro   from_base,value
  187.     mov    dx,cs:[io_adr]        ; write byte value to port
  188.     add    dx,from_base
  189.     mov    al,value
  190.     out    dx,al
  191.     endm
  192.  
  193. readbport  macro  from_base
  194.     mov    dx,cs:[io_adr]
  195.     add    dx,from_base
  196.     in    al,dx
  197.     endm
  198.  
  199. port    macro    from_base
  200.     mov    dx,cs:[io_adr]
  201.     add    dx,from_base
  202.     endm
  203.  
  204. ;sends $ terminated string to screen
  205. print$ macro   string
  206.     mov    ah,9
  207.     mov    dx,offset &string&    ; print $ terminated string
  208.     int    21h
  209.     endm
  210.  
  211. mark           = 0F90h                 ; marker debug pos on screen 25
  212.  
  213. marker  macro   st,nd
  214.   IF  debug NE 0                       ; do marker if debug <> 0
  215.       pushf                            ; show 2 char marker on
  216.       push es                          ; 25th line, 1st column
  217.       push ax
  218.       mov  ax,0B800h
  219.       mov  es,ax
  220.       mov  al,'&st&'
  221.       mov  byte ptr es:[mark],al
  222.       mov  al,byte ptr es:[mark+1]     ; get color value
  223.       inc  al
  224.       and  al,0Fh
  225.       or   al,1
  226.       mov  byte ptr es:[mark+1],al     ; advance it to show activity
  227.       mov  al,'&nd'
  228.       mov  byte ptr es:[mark+2],al
  229.       mov  al,byte ptr es:[mark+3]
  230.       inc  al
  231.       and  al,0Fh
  232.       or   al,1
  233.       mov  byte ptr es:[mark+3],al
  234.       pop  ax
  235.       pop  es
  236.       popf
  237.     ENDIF
  238.   endm
  239.  
  240.     public    as_send_pkt
  241. ; The Asynchronous Transmit Packet routine.
  242. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  243. ;   interrupts possibly enabled.
  244. ; Exit with nc if ok, or else cy if error, dh set to error number.
  245. ;   es:di and interrupt enable flag preserved on exit.
  246. as_send_pkt:
  247.     ret
  248.  
  249.     public    drop_pkt
  250. ; Drop a packet from the queue.
  251. ; Enter with es:di -> iocb.
  252. drop_pkt:
  253.     assume    ds:nothing
  254.     ret
  255.  
  256.     public    xmit
  257. ; Process a transmit interrupt with the least possible latency to achieve
  258. ;   back-to-back packet transmissions.
  259. ; May only use ax and dx.
  260. xmit:
  261.     assume    ds:nothing
  262.     ret
  263.  
  264.  
  265.     public    send_pkt
  266. send_pkt:
  267. ;enter with ds:si -> packet, cx = packet length.
  268. ;exit with nc if ok, pr else cy if error, dh set to error number.
  269.  
  270.               assume  ds:nothing
  271.               marker  T,X
  272.               inc     cx
  273.               and     cx,not 1                ; round to nearest even number
  274.               cmp     cx,RUNT                 ; big enough?
  275.               jae     send_runt_ok
  276.               mov     cx,RUNT                 ; at least runt!
  277. send_runt_ok:
  278.               cmp     cx,GIANT                ; small enough?
  279.               jle     send_size_ok
  280.               stc                             ; Error
  281.               ret
  282. send_size_ok:
  283.               push    cx
  284.               shr     cx,1                    ; words to send
  285. ;
  286. ;      8086/8088 byte mode send
  287. ;
  288.               mov     dx,cs:[io_adr]
  289.               add     dx,BMPR_MEM_PORT
  290.               cmp     cs:is_186,0  ; use BYTE or WORD mode?
  291.               jne     send_w_mode
  292.               cld
  293.  xb:
  294.               lodsw                           ; load word, ind ds:si
  295.               out     dx,al
  296.               xchg    ah,al
  297.               out     dx,al
  298.               loop    xb                      ; set packet length (byte mode)
  299.               pop     ax
  300.               or      ah,TMST
  301.               mov     dx,cs:[io_adr]
  302.               add     dx,BMPR_PKT_LEN
  303.               out     dx,al                   ; write BMPR2, then BMPR3 to
  304.               xchg    al,ah                   ; initiate byte mode transmit
  305.               inc     dx
  306.               out     dx,al
  307.               jmp     wait_tmt_ok
  308. send_w_mode:
  309.               cld
  310.               rep
  311.     db    0f3h, 06fh    ;masm 4.0 doesn't grok "rep outsw"
  312.               pop     ax
  313.               or      ah,TMST
  314.               mov     dx,cs:[io_adr]
  315.               add     dx,BMPR_PKT_LEN
  316.               out     dx,ax
  317. wait_tmt_ok:
  318.               xor     cx,cx
  319.               mov     dx,cs:[io_adr]
  320.               IF DLCR_XMIT_STAT NE 0
  321.                  add     dx,DLCR_XMIT_STAT
  322.               ENDIF
  323. wait_tmt:
  324.               in      al,dx            ; read status register until timeout...
  325.               test    al,TMT_OK
  326.               jnz     send_ok
  327.               loop    wait_tmt
  328.               stc
  329.               ret
  330. send_ok:
  331.               clc
  332.               ret
  333. public  get_address
  334. get_address:
  335.                                             ;get the address on the interface.
  336.     ;enter with es:di -> place to get the address, cx = size of address buffer
  337.     ;exit with nc, cx = actual size of address, or cy if buffer not big enough
  338.     ;
  339.               assume  ds:code
  340.     cmp    cx,EADDR_LEN                   ; enough room for address?
  341.     jge    get_adr_ok
  342.         stc
  343.         ret
  344. get_adr_ok:
  345.     push    bx
  346.         mov     cx,EADDR_LEN
  347.         mov     bx,0
  348. get_adr:
  349.         mov     al,cs:eeaddr[bx]
  350.         inc     bx
  351.         stosb
  352.         loop    get_adr
  353.         mov     cx,EADDR_LEN
  354.         clc
  355.     pop    bx
  356.         ret
  357.  
  358.     public  set_address
  359. set_address:
  360. ;enter with ds:si -> Ethernet address,CX = length of address.
  361. ;exit with nc if okay, or cy, dh=error if any errors.
  362.     assume    ds:nothing
  363.     ret
  364.  
  365.  
  366. rcv_mode_1:
  367.     writebport    DLCR_RECV_MODE,0    ; don't receive any packets
  368.     ret
  369.  
  370.  
  371. rcv_mode_3:
  372.     writebport    DLCR_RECV_MODE,2    ; receive mine, broads, and multis.
  373.     ret
  374.  
  375.  
  376. rcv_mode_6:
  377.     writebport    DLCR_RECV_MODE,3    ; receive all packets.
  378.     ret
  379.  
  380.  
  381.     public  set_multicast_list
  382. set_multicast_list:
  383. ;enter with es:di ->list of multicast addresses, cx = number of bytes.
  384. ;return nc if we set all of them, or cy,dh=error if we didn't.
  385.  
  386.     mov     dh,NO_MULTICAST
  387.     stc
  388.     ret
  389.  
  390.     public  get_multicast_list
  391. get_multicast_list:
  392. ;return with nc, es:di ->list of multicast addresses, cx = number of bytes.
  393. ;return cy, NO_ERROR if we don't remember all of the addresses ourselves.
  394. ;return cy, NO_MULTICAST if we don't implement multicast.
  395.  
  396.     mov     dh,NO_MULTICAST
  397.     stc
  398.     ret
  399.  
  400.     public    terminate
  401. terminate:
  402.     writebport    DLCR_RECV_MODE,0    ; don't receive any packets
  403.     ret
  404.  
  405.     public  reset_interface
  406. reset_interface:                       ;reset the interface.
  407.     assume  ds:code
  408.     ret
  409.  
  410. ;called when we want to determine what to do with a received packet.
  411. ;enter with cx = packet length, es:di -> packet type, dl = packet class.
  412.     extrn   recv_find: near
  413.  
  414. ;called after we've copied the packet into the buffer.
  415. ;enter with ds:si ->the packet, cx = length of the packet.
  416.     extrn   recv_copy: near
  417.  
  418.     extrn   count_in_err: near
  419.     extrn   count_out_err: near
  420.  
  421.     public  recv
  422. recv:
  423. ;called from the recv isr.  All registers have been saved, and ds=cs.
  424. ;Upon exit, the interrupt will be acknowledged.
  425.  
  426.     assume  ds:code
  427.     marker  R,X
  428.  
  429. ;clear receive masks to prevent further IRQs
  430.  
  431.     writebport    DLCR_RECV_MASK,0
  432.     cli
  433. recv_0:
  434.     mov     ax,cs
  435.     mov     ds,ax
  436.     writebport      DLCR_RECV_STAT,clr_rcv_status
  437.  
  438. ;are there any packets to read?
  439.  
  440.     mov     dx,cs:[io_adr]
  441.     add     dx,DLCR_RECV_MODE
  442.     in      al,dx
  443.     test    al,BUF_EMPTY
  444.     jz      recv_1                    ; 0 if at least one valid pkt..
  445.     jmp     recv_99
  446.  
  447. ;yes, read out a receive packet...
  448.  
  449. recv_1:
  450.               cmp     cs:is_186,0
  451.               jne     recv11
  452.               jmp     read_b_mode
  453. ;
  454. ;        read packet out in word mode
  455. ;
  456. recv11:
  457.     mov    dx,cs:[io_adr]    ; get status and reserved byte
  458.     add    dx,BMPR_MEM_PORT
  459.     in    ax,dx
  460.     in    ax,dx                           ; get packet size
  461.     inc    ax                              ; convert to words
  462.     and    ax,not 1                        ; save it for copy out...
  463.     push    ax
  464.                     ;read first 14 bytes from receive buffer into ether_buff
  465.     mov    ax,cs
  466.     mov    es, ax
  467.     mov    di,offset ether_buff
  468.     mov    cx,16/2                            ; word mode, remember...
  469.     cld
  470. ;    rep    insw            ; read words into ether_buff
  471.     db    0f3h, 06dh    ;masm 4.0 doesn't grok "rep insw"
  472.  
  473. ;
  474. ;      If the sender is myself, ignore the packet.  This allows async
  475. ;      send/receive without messing up...
  476. ;
  477.     mov    si,offset ether_buff+EADDR_LEN       ; we want the SOURCE
  478.     mov    cx,EADDR_LEN
  479.     mov    bx,0
  480. my_send:
  481.     mov    al,cs:eeaddr[bx]
  482.     inc    bx
  483.     cmp    al,byte ptr ds:[si]
  484.     jne    not_mine
  485.     inc    si
  486.     loop    my_send
  487.     jmp    word_flush                      ; mine, so flush it
  488. ;
  489. ;      cx = length, es:di = pointer to ethertype
  490. ;
  491. not_mine:
  492.     pop    cx
  493.     push    cx
  494.     mov    di,offset ether_type
  495.     mov    ax,cs
  496.     mov    es,ax            ; es:di -> ether type, cx = size# bytes
  497.     mov    dl, BLUEBOOK        ;assume bluebook Ethernet.
  498.     mov    ax, es:[di]
  499.     xchg    ah, al
  500.     cmp     ax, 1500
  501.     ja    BlueBookPacket
  502.     inc    di            ;set di to 802.2 header
  503.     inc    di
  504.     mov    dl, IEEE8023
  505. BlueBookPacket:
  506.     call    recv_find        ; got a buffer?
  507.     mov    ax,es
  508.     or    ax,di            ; pointer zero?
  509.     je    word_flush        ; no pointer, discard data
  510. ;
  511. ;      es:di -> users buffer, do copy...
  512. ;      ds:si -> source of copy
  513. ;
  514.     mov    cs:[usr_ptr.segm],es; save ULP pointer
  515.     mov    cs:[usr_ptr.offs],di
  516.     mov    ax,cs
  517.     mov    ds,ax
  518.     mov    si,offset ether_buff    ; copy header to users buffer
  519.     mov    cx,16/2            ; 8 words to copy
  520.     cld
  521.     rep    movsw
  522.     mov    dx,cs:[io_adr]        ;copy rest of data to user
  523.     add    dx,BMPR_MEM_PORT    ; buffer in es:di ->
  524.     pop    cx
  525.     push    cx
  526.     sub    cx,16
  527.     shr    cx,1
  528.     cld
  529. ;    rep    insw            ; read word, store at es:di ->
  530.     db    0f3h, 06dh    ;masm 4.0 doesn't grok "rep insw"
  531.     pop    cx            ;call recv_copy to say copy done
  532.     lds    si,cs:[usr_ptr]
  533.     call    recv_copy
  534.     jmp    recv_0            ; go get another packet
  535. word_flush:
  536.     mov    dx,cs:[io_adr]
  537.     add    dx,BMPR_MEM_PORT
  538.     pop    cx
  539.     sub    cx,16            ; adjust word count
  540.     shr    cx,1
  541. word_f:
  542.     in    ax,dx
  543.     loop    word_f
  544.     jmp    recv_0
  545. ;
  546. ;             go see of any more packets comming....
  547. ;
  548. ;             READ in BYTE MODE
  549. ;
  550. read_b_mode:
  551.     mov    dx,cs:[io_adr]    ;get status and reserved byte
  552.     add    dx,BMPR_MEM_PORT
  553.     in    al,dx        ; vacuum status and reserved
  554.     in    al,dx
  555.     in    al,dx        ; get packet size
  556.     xchg    al,ah        ; low byte in ah
  557.     in    al,dx        ; get packet size
  558.     xchg    al,ah        ; fix size ah/al order
  559.     push    ax        ; keep number of bytes
  560.     ;      read first 16 bytes from receive buffer into ether_buff
  561.     mov    ax,cs
  562.     mov    es,ax
  563.     mov    di,offset ether_buff
  564.     mov    cx,16            ; byte mode, 16 byte header
  565.     cld
  566. rdb:
  567.     in    al,dx            ; read 16 bytes into ether_buff
  568.     stosb
  569.     loop    rdb
  570. ;
  571. ;      If the sender is myself, ignore the packet.
  572. ;
  573.     mov    si,offset ether_buff+EADDR_LEN; we want the SOURCE...
  574.     mov    cx,EADDR_LEN
  575.     mov    bx,0
  576. my_sendb:
  577.     mov    al,cs:eeaddr[bx]
  578.     inc    bx
  579.     cmp    al,byte ptr ds:[si]
  580.     jne    not_mineb
  581.     inc    si
  582.     loop    my_sendb
  583.     jmp    byte_flush                  ; mine, so flush it
  584. ;
  585. ;      cx = length, es:di = pointer to ethertype
  586. ;
  587. not_mineb:
  588.     pop    cx
  589.     push    cx
  590.     mov    di,offset ether_type
  591.     mov    ax,cs
  592.     mov    es,ax             ; es:di -> ether type, cx = size#bytes
  593.     mov    dl, BLUEBOOK        ;assume bluebook Ethernet.
  594.     mov    ax, es:[di]
  595.     xchg    ah, al
  596.     cmp     ax, 1500
  597.     ja    BlueBookPacket1
  598.     inc    di            ;set di to 802.2 header
  599.     inc    di
  600.     mov    dl, IEEE8023
  601. BlueBookPacket1:
  602.     call    recv_find                   ; got a buffer?
  603.     mov    ax,es
  604.     or    ax,di                       ; pointer zero?
  605.     je    byte_flush                  ; no pointer, discard data
  606. ;
  607. ;      es:di -> users buffer, do copy...
  608. ;      ds:si -> source of copy
  609. ;
  610.     mov    cs:[usr_ptr.segm],es    ; save ULP pointer
  611.     mov    cs:[usr_ptr.offs],di
  612.     mov    ax,cs
  613.     mov    ds,ax
  614.     mov    si,offset ether_buff        ; copy header to users buffer
  615.     mov    cx,16                       ; 16 bytes in header to copy
  616.     cld
  617.     rep
  618.     movsb
  619.     mov    dx,cs:io_adr     ; copy rest of data to users
  620.     add    dx,BMPR_MEM_PORT            ; buffer in es:di ->
  621.     pop    cx
  622.     push    cx
  623.     sub    cx,14
  624.     cld
  625. cpyb:
  626.     in    al,dx            ; read byte
  627.     stosb                ; store at es:di ->
  628.     loop    cpyb
  629.     pop    cx            ; call recv_copy to say copy done
  630.     lds    si,cs:[usr_ptr]
  631.     call    recv_copy
  632.     jmp    recv_0            ; go get another packet...
  633. byte_flush:
  634.     mov    dx,cs:io_adr
  635.     add    dx,BMPR_MEM_PORT
  636.     pop    cx
  637.     sub    cx,16            ; adjust byte count header
  638. byte_f:
  639.     in    al,dx
  640.     loop    byte_f
  641.     jmp    recv_0            ; go to see if any more packets comming...
  642. recv_99:
  643. ;      receive ok, restore recive mask and exit
  644. ;
  645.     writebport    DLCR_RECV_MASK,en_rcv_irqs
  646.     ret
  647.  
  648.  
  649.     public    recv_exiting
  650. recv_exiting:
  651. ;called from the recv is after interrupts have been acknowledged.
  652. ;Only ds and ax have been saved.
  653. ;
  654.     assume    ds:nothing
  655.     ret
  656.  
  657. ;any code after this will not be kept after initialization.
  658.  
  659. end_resident    label    byte
  660.  
  661. io_adr_msg    db    "I/O Base Address: ",'$'
  662. int_no_msg    db    " Interrupt Level: ",'$'
  663. no_card_msg    db    "INIT: No card at I/O address specified",CR,LF,'$'
  664. is_186_msg    db    "INIT: Using WORD I/O mode.",CR,LF,'$'
  665. not_186_msg    db    "INIT: Using BYTE I/O mode.",CR,LF,'$'
  666. installed_ok    db    "INIT: Installation Complete",CR,LF,'$'
  667.  
  668.     public  usage_msg
  669. usage_msg   db  "usage: EN301 [-n] [-d] [-w] <packet_int_no> <int_no> <io_addr>",CR,LF,'$'
  670.  
  671.     public  copyright_msg
  672. copyright_msg    label    byte
  673.  db CR,LF
  674.  db "EN301:   FTP Driver for Multi-Tech EN301, Version ",'0'+(majver / 10),'0'+(majver mod 10),".",'0'+version, CR,LF
  675.  db "         - for PC and PC-AT",CR,LF
  676.  db "portions - Copyright 1991 by Chris Elmquist and",CR,LF
  677.  db "           Copyright 1990, 1991 Queens University by Brian Fisher",CR,LF
  678.  db CR,LF,'$'
  679.  
  680.     extrn   set_recv_isr: near
  681. ;enter with si-> argument string,di->wword to store.
  682. ;if there is no number, don't change  the number.
  683.  
  684. ;enter with si -> argument string, di -> word to store.
  685. ;if there is no number, don't change the number.
  686.     extrn   get_number: near
  687.  
  688. ;enter with dx -> name of word, di -> dword to print.
  689.     extrn    print_number: near
  690.  
  691.     public  parse_args
  692. parse_args:
  693.  
  694. ;      parse I/O base address and hardware interrupt number from the
  695. ;      command line.
  696. ;
  697.     mov    bx,offset int_no_msg    ; first comes the interrupt level
  698.     mov    di,offset int_no
  699.     call    get_number
  700.     jc    _parse_exit
  701.     mov    bx,offset io_adr_msg    ; then the I/O base address
  702.     mov    di,offset io_adr
  703.     call    get_number
  704. _parse_exit:
  705.     clc
  706.     ret
  707.  
  708. ; Clock the LSB of AX into the EEPROM (DI is inverted by the hardware)
  709. clkbit:
  710.     push    ax
  711.     port    EEDI_PORT
  712.     not    ax        ; invert data because of hardware
  713.     out    dx,al
  714.     mov    al,1        ; clock high
  715.     port    EECLK_PORT
  716.     out    dx,al
  717.     mov    al,0        ; clock low
  718.     out    dx,al
  719.     pop    ax
  720.     ret
  721.  
  722.     public etopen
  723. etopen:
  724. ;
  725. ;      Set Node ID:
  726. ;
  727.     writebport    EECS_PORT,1    ; CS high on 9346
  728.     mov    al,0
  729.     call    clkbit
  730.  
  731. ; clock the 6 byte (3 words) Ethernet address out of the EEPROM
  732.     mov    cx,3
  733.     mov    bx,0
  734. eegetadr1:
  735.     mov    al,1        ; READ opcode is '110'
  736.     call    clkbit
  737.     call    clkbit
  738.     mov    al,0
  739.     call    clkbit
  740.     mov    ax,bx
  741.     shr    ax,1
  742.  
  743. ; send the address in AX to EEPROM
  744.     push    cx
  745.     mov    cx,5
  746.     ror    ax,cl        ; move A5 to LSB
  747.     call    clkbit
  748. saddr1:    rol    ax,1        ; A4 to LSB, then A3, etc...
  749.     call    clkbit        ; LSB of AX gets clocked in
  750.     loop    saddr1        
  751.  
  752. ; read the data from the currently addressed EEPROM cell
  753.     push    bx
  754.     mov    cx,16        ; set counter to read 16 bits of data
  755.     mov    bx,0
  756. rdd:    shl    bx,1
  757.     call    clkbit
  758.     readbport    EEDO_PORT
  759.     and    ax,1
  760.     or    bx,ax
  761.     loop    rdd
  762.     mov    al,bh
  763.     mov    ah,bl
  764.     pop    bx
  765.     pop    cx
  766.  
  767.     mov    word ptr cs:eeaddr[bx],ax
  768.     inc    bx
  769.     inc    bx
  770.  
  771. ; perform a standby operation after each read
  772.     writebport    EECS_PORT,0
  773.     call    clkbit
  774.     call    clkbit
  775.     writebport    EECS_PORT,1
  776.     loop    eegetadr1
  777.  
  778.     writebport    EECS_PORT,0    ; deselect the EEPROM and de-reset
  779.                     ; the Fujitsu
  780.  
  781.     writebport    DLCR_ENABLE,card_disable    ; disable etherstar
  782.     writebport    DLCR_XMIT_STAT,clear_status    ; clr xmit status
  783.     writebport    DLCR_XMIT_MASK,no_tx_irqs    ; disable xmit IRQ's
  784.     writebport    DLCR_RECV_STAT,clr_rcv_status    ; clear rcv status
  785.     writebport    DLCR_RECV_MASK,en_rcv_irqs    ; enable rcv IRQ's
  786.     writebport    DLCR_XMIT_MODE,xmit_mode    ; set xmit mode
  787.     writebport    DLCR_RECV_MODE,recv_mode    ; set receive mode
  788.  
  789.     mov    bx,0            ; write the node address
  790.     mov    cx,6            ; into the 86950 registers
  791.     port    DLCR_NODE_ID
  792. etopen1:
  793.     mov    al,cs:eeaddr[bx]
  794.     out    dx,al
  795.     inc    dx
  796.     inc    bx
  797.     loop    etopen1
  798.  
  799. ;Determine the processor type.  The 8088 and 8086 will actually shift ax
  800. ;over by 33 bits, while the 80[123]86 use a shift count mod 32.
  801.  
  802.     mov    cl,33
  803.     mov    ax,0ffffh
  804.     shl    ax,cl            ; Thanks to Russ Nelson for this little
  805.     jz    not_186            ; bit of 'clip art'.
  806.     mov    is_186,1
  807.     print$    is_186_msg
  808.     jmp    etopen2
  809. not_186:
  810.     print$  not_186_msg
  811. etopen2:
  812.                     ; vacuum data port until BUF_EMPTY
  813.     mov    dx,cs:io_adr
  814.     mov    bx,dx
  815.     add    bx,DLCR_RECV_MODE
  816.     add    dx,BMPR_MEM_PORT
  817.     cmp    cs:is_186,0
  818.     je    vac_88
  819. vac_86:
  820.     in    ax,dx
  821.     xchg    dx,bx
  822.     in    ax,dx
  823.     xchg    dx,bx
  824.     test    al,BUF_EMPTY
  825.     jz    vac_86
  826.     jmp    all_done
  827. vac_88:
  828.     in    al,dx
  829.     xchg    dx,bx
  830.     in    al,dx
  831.     xchg    dx,bx
  832.     test    al,BUF_EMPTY
  833.     jz    vac_88
  834. all_done:
  835.     writebport    DLCR_ENABLE,card_enable
  836.     call    set_recv_isr                ; install receive IRQ routine
  837.  
  838.     mov    al, int_no        ; Get board's interrupt vector
  839.     add    al, 8
  840.     cmp    al, 8+8            ; Is it a slave 8259 interrupt?
  841.     jb    set_int_num        ; No.
  842.     add    al, 70h - 8 - 8        ; Map it to the real interrupt.
  843. set_int_num:
  844.     xor    ah, ah            ; Clear high byte
  845.     mov    int_num, ax        ; Set parameter_list int num.
  846.  
  847.     print$    installed_ok                ; if all is okay,
  848.     mov    dx,offset end_resident
  849.     clc
  850.     ret
  851.  
  852.     public    print_parameters
  853. print_parameters:
  854. ;echo our command-line parameters
  855.     mov    di,offset io_adr    ; first comes the I/O base address
  856.     mov    dx,offset io_adr_msg
  857.     call    print_number
  858.     mov    di,offset int_no    ; interrupt level?
  859.     mov    dx,offset int_no_msg
  860.     call    print_number
  861.     ret
  862.  
  863. code    ends
  864.  
  865.     end
  866.